package com.bai;

import com.sinoservices.hichain.scc.module.entity.*;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.Date;

/**
 * @version Revision 1.0.0
 * @cLASSnAME CreateMybatilsByCondition
 * @版权：SINOSERVICES 版权所有 (c) 2013
 * @author:Felix
 * @email:Felix.Bai@sinoservices.com
 * @see:
 * @创建日期：2019/4/12 14:23
 * @功能说明：
 * @begin
 * @修改记录:
 * @end
 */
public class CreateMybatilsByCondition {

    public static final String FIND_BY_CONDITION_BENGIN = "<select id=\"find{0}ByCondition\" resultMap=\"BaseResultMap\" parameterType=\"com.sinoservices.hichain.scc.module.entity.{1}Condition\" >\n" +
            "    SELECT \n" +
            "        *\n" +
            "    FROM\n" +
            "        {2} where 1=1";
    public static final String FIND_BY_CONDITION_CENTER_CONDITION = "    <if test=\"{0}.{1} != null and {2}.{3} != ''''\" >\n" +
            "        AND {4} {5}\n" +
            "    </if>";
    public static final String FIND_BY_CONDITION_END ="    <if test=\"{0}.orderByClause != null and {1}.orderByClause != ''''\" >\n" +
            "        order by $'{'{2}.orderByClause'}'\n" +
            "    </if>\n" +
            "</select>";

    public static final String COUNT_BY_CONDITION_BENGIN = "<select id=\"count{0}ByCondition\" resultType=\"java.lang.Integer\" parameterType=\"com.sinoservices.hichain.scc.module.entity.{1}Condition\" >\n" +
            "    SELECT \n" +
            "        count(1) \n" +
            "    FROM\n" +
            "        {2} where 1=1";
    public static final String COUNT_BY_CONDITION_CENTER_CONDITION = "    <if test=\"{0}.{1} != null and {2}.{3} != ''''\" >\n" +
            "        AND {4} {5}\n" +
            "    </if>";
    public static final String COUNT_BY_CONDITION_END ="</select>";

    public static String ignores = "orderByClause,serialVersionUID";

    public static void main(String[] args) {

        //createFindByCondition(FeeRecordCondition.class);
        createFindByCondition(ContractCondition.class);
        createCountByCondition(ContractCondition.class);
    }

    public static void createFindByCondition(Class clazz){
        String className = clazz.getSimpleName().replaceAll("Condition","");//去掉condition
        String tableName = formatToSqlName(className).substring(1);
        String newClassName = lowerFirst(className);//新实例名字
        String newConditionClassName = lowerFirst(className)+"Condition";//新条件实例名字
        String mainKey_FILED = newClassName+"Id";
        String mainKey_SQL = formatToSqlName(mainKey_FILED);

        Field[] fields = clazz.getDeclaredFields();
        System.out.println(MessageFormat.format(FIND_BY_CONDITION_BENGIN,className,className,tableName));
        for(int i = 0 ; i < fields.length ; i++) {
            if(ignores.indexOf(fields[i].getName()) != -1){
                continue;
            }

            System.out.println(MessageFormat.format(FIND_BY_CONDITION_CENTER_CONDITION,
                    newConditionClassName,
                    fields[i].getName(),
                    newConditionClassName,
                    fields[i].getName(),
                    formatToSqlName(fields[i].getName()).replaceAll("_FROM","").replaceAll("_TO",""),
                    //>= #{salesOrderCondition.examineTimeFrom}
                    checkFieldType(newConditionClassName,fields[i].getName(),fields[i])
                    ));
        }
        System.out.println(MessageFormat.format(FIND_BY_CONDITION_END,newConditionClassName,newConditionClassName,newConditionClassName));
    }

    public static void createCountByCondition(Class clazz){
        String className = clazz.getSimpleName();
        String tableName = formatToSqlName(className).substring(1);
        String newClassName = lowerFirst(className);//新实例名字
        String newConditionClassName = lowerFirst(className)+"Condition";//新条件实例名字
        String mainKey_FILED = newClassName+"Id";
        String mainKey_SQL = formatToSqlName(mainKey_FILED);

        Field[] fields = clazz.getDeclaredFields();
        System.out.println(MessageFormat.format(COUNT_BY_CONDITION_BENGIN,className,className,tableName));
        for(int i = 0 ; i < fields.length ; i++) {
            if(ignores.indexOf(fields[i].getName()) != -1){
                continue;
            }

            System.out.println(MessageFormat.format(COUNT_BY_CONDITION_CENTER_CONDITION,
                    newConditionClassName,
                    fields[i].getName(),
                    newConditionClassName,
                    fields[i].getName(),
                    formatToSqlName(fields[i].getName()).replaceAll("_FROM","").replaceAll("_TO",""),
                    //>= #{salesOrderCondition.examineTimeFrom}
                    checkFieldType(newConditionClassName,fields[i].getName(),fields[i])
            ));
        }
        System.out.println(COUNT_BY_CONDITION_END);
    }

    private static String checkFieldType(String newConditionClassName, String fieldName, Field field) {
        if (field.getType() == Long.class
                || field.getType() == BigDecimal.class
                || field.getType() == Short.class
                || field.getType() == Integer.class) {
            //= #{salesOrderCondition.paymentStatus,jdbcType=VARCHAR}
            return " = #{" + newConditionClassName + "."+fieldName + ",jdbcType=" + formatFieldTypeToSqlType(field.getType()) + "}";
        } else if (field.getType() == Date.class) {
            if(fieldName.toUpperCase().contains("FROM")){
                return " >= #{" + newConditionClassName + "."+fieldName + ",jdbcType=" + formatFieldTypeToSqlType(field.getType()) + "}";
            }else if (fieldName.toUpperCase().contains("TO")){
                return " &lt;= #{" + newConditionClassName + "."+fieldName + ",jdbcType=" + formatFieldTypeToSqlType(field.getType()) + "}";
            }else{
                return " = #{" + newConditionClassName + "."+fieldName + ",jdbcType=" + formatFieldTypeToSqlType(field.getType()) + "}";
            }
        }else if(field.getType() == String.class){
            if(fieldName.toUpperCase().contains("STATUS") || fieldName.toUpperCase().contains("TYPE")){
                return " = #{" + newConditionClassName + "."+fieldName + ",jdbcType=" + formatFieldTypeToSqlType(field.getType()) + "}";
            }else{
                // like '%${salesOrderCondition.creator}%'
                //return " like '%${" + newConditionClassName + "."+fieldName + ",jdbcType=" + formatFieldTypeToSqlType(field.getType()) + "}%'";
                return " like '%${" + newConditionClassName + "."+fieldName + "}%'";
            }
        }else{
            System.out.println("------------------------------------------------------------------------------------------------------------");
            System.out.println("异常类型，请添加规则："+field.getType().toString());
            System.out.println("------------------------------------------------------------------------------------------------------------");
            return "";
        }
    }

    public static String formatFieldTypeToSqlType(Class<?> type) {
        if(type == Long.class){
            return "BIGINT";
        }else if(type == BigDecimal.class){
            return "DECIMAL";
        }else if(type == Short.class){
            return "SMALLINT";
        }else if(type == Integer.class){
            return "Integer";
        }else if(type == Date.class){
            return "TIMESTAMP";
        }else if(type == String.class){
            return "VARCHAR";
        }else{
            System.out.println("------------------------------------------------------------------------------------------------------------");
            System.out.println("未知字段类型，请添加转换规则："+type.toString());
            System.out.println("------------------------------------------------------------------------------------------------------------");
            return "";
        }

    }


    public static String formatToSqlName(String fieldName){
        StringBuffer sb = new StringBuffer();
        char[] ch = fieldName.toCharArray();
        for (char c:ch){
            sb.append(upChar(c));
        }
        return sb.toString();
    }

    public static String upChar(char c){
        if(c>='a' && c<='z') {
            return String.valueOf(c).toUpperCase();
        }else if(c>='A' && c<='Z') {
            return "_"+String.valueOf(c).toUpperCase();
        }else if(c>='0' && c<='9'){
            return String.valueOf(c).toUpperCase();
        }else{
            return "";
        }
    }

    public static String lowerFirst(String name){
        char[] chars = name.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }

}
